<?php

namespace Gnway\Util\Concurrent;

use Exception, InvalidArgumentException;

/**
 * Class Pool
 *
 * @author zushaolong
 * @mail zushaolong@gmail.com
 */
class Pool extends AbstractPool
{

  /** @inheritDoc */
  protected function scheduler(): void
  {
    try {
      foreach ($this->processes as $proc) {
        $proc->isRunning() || $proc->start();
      }
    } catch (Exception $ex) {
      echo 'Process startup: ' . $ex->getMessage() . PHP_EOL;
    }
  }

  /** @inheritDoc */
  public function shutdown(int $signal = SIGTERM): void
  {
    foreach ($this->processes as $process) {
      try {
        $process->isRunning() && $process->shutdown($signal);
      } catch (Exception $ex) {
        echo $ex->getMessage() . PHP_EOL;
      }
    }
  }

  /** @inheritDoc */
  public function wait(int $timeout = 0): void
  {
    if ($timeout < -1) {
      throw new InvalidArgumentException('timeout value is illegal');
    }

    $now = time();
    $processes = $this->processes;

    while ($processes) {
      $process = array_shift($processes);
      if (!$process->isRunning()) {
        continue;
      }

      $process->wait(-1);
      $processes[] = $process;

      if ($timeout > 0 && time() - $now > $timeout) {
        throw new WaitException('Wait pool timeout ' . $timeout . 'sec');
      }
      elseif ($timeout !== 0) {
        break;
      }

      usleep(10);
    }
  }
}